{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "whjsJasuhstV"
   },
   "source": [
    "<a href=\"https://colab.research.google.com/github/jeffheaton/app_generative_ai/blob/main/t81_559_class_07_4_more_agent.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "euOZxlIMhstX"
   },
   "source": [
    "# T81-559: Applications of Generative Artificial Intelligence\n",
    "**Module 7: LangChain: Agents**\n",
    "* Instructor: [Jeff Heaton](https://sites.wustl.edu/jeffheaton/), McKelvey School of Engineering, [Washington University in St. Louis](https://engineering.wustl.edu/Programs/Pages/default.aspx)\n",
    "* For more information visit the [class website](https://sites.wustl.edu/jeffheaton/t81-558/)."
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "d4Yov72PhstY"
   },
   "source": [
    "# Module 7 Material\n",
    "\n",
    "* Part 7.1: Introduction to LangChain Agents [[Video]](https://www.youtube.com/watch?v=J5Vr___lSSs) [[Notebook]](t81_559_class_07_1_agents.ipynb)\n",
    "* Part 7.2: Understanding LangChain Agent Tools [[Video]](https://www.youtube.com/watch?v=qMquBmteYw4) [[Notebook]](t81_559_class_07_2_tools.ipynb)\n",
    "* Part 7.3: LangChain Retrival and Search Tools [[Video]](https://www.youtube.com/watch?v=NB5qGPLoBBE) [[Notebook]](t81_559_class_07_3_search_tools.ipynb)\n",
    "* **Part 7.4: Constructing LangChain Agents** [[Video]](https://www.youtube.com/watch?v=OJe5oHvrdHk) [[Notebook]](t81_559_class_07_4_more_agent.ipynb)\n",
    "* Part 7.5: Custom Agents [[Video]](https://www.youtube.com/watch?v=IsJemVYSEdc) [[Notebook]](t81_559_class_07_5_custom_agent.ipynb)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "AcAUP0c3hstY"
   },
   "source": [
    "# Google CoLab Instructions\n",
    "\n",
    "The following code ensures that Google CoLab is running and maps Google Drive if needed."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 1,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "xsI496h5hstZ",
    "outputId": "56693c69-259b-4a0e-8b3a-3c400869a5f8"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Note: using Google CoLab\n",
      "Collecting langchain\n",
      "  Downloading langchain-0.2.6-py3-none-any.whl (975 kB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m975.5/975.5 kB\u001b[0m \u001b[31m4.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hCollecting langchain_openai\n",
      "  Downloading langchain_openai-0.1.13-py3-none-any.whl (45 kB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m45.9/45.9 kB\u001b[0m \u001b[31m2.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hCollecting langchain_experimental\n",
      "  Downloading langchain_experimental-0.0.62-py3-none-any.whl (202 kB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m202.7/202.7 kB\u001b[0m \u001b[31m11.8 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hCollecting duckduckgo-search\n",
      "  Downloading duckduckgo_search-6.1.7-py3-none-any.whl (24 kB)\n",
      "Collecting langchainhub\n",
      "  Downloading langchainhub-0.1.20-py3-none-any.whl (5.0 kB)\n",
      "Collecting sentence-transformers\n",
      "  Downloading sentence_transformers-3.0.1-py3-none-any.whl (227 kB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m227.1/227.1 kB\u001b[0m \u001b[31m8.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hCollecting faiss-cpu\n",
      "  Downloading faiss_cpu-1.8.0.post1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (27.0 MB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m27.0/27.0 MB\u001b[0m \u001b[31m34.4 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hRequirement already satisfied: PyYAML>=5.3 in /usr/local/lib/python3.10/dist-packages (from langchain) (6.0.1)\n",
      "Requirement already satisfied: SQLAlchemy<3,>=1.4 in /usr/local/lib/python3.10/dist-packages (from langchain) (2.0.31)\n",
      "Requirement already satisfied: aiohttp<4.0.0,>=3.8.3 in /usr/local/lib/python3.10/dist-packages (from langchain) (3.9.5)\n",
      "Requirement already satisfied: async-timeout<5.0.0,>=4.0.0 in /usr/local/lib/python3.10/dist-packages (from langchain) (4.0.3)\n",
      "Collecting langchain-core<0.3.0,>=0.2.10 (from langchain)\n",
      "  Downloading langchain_core-0.2.10-py3-none-any.whl (332 kB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m332.8/332.8 kB\u001b[0m \u001b[31m25.5 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hCollecting langchain-text-splitters<0.3.0,>=0.2.0 (from langchain)\n",
      "  Downloading langchain_text_splitters-0.2.2-py3-none-any.whl (25 kB)\n",
      "Collecting langsmith<0.2.0,>=0.1.17 (from langchain)\n",
      "  Downloading langsmith-0.1.82-py3-none-any.whl (127 kB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m127.4/127.4 kB\u001b[0m \u001b[31m8.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hRequirement already satisfied: numpy<2,>=1 in /usr/local/lib/python3.10/dist-packages (from langchain) (1.25.2)\n",
      "Requirement already satisfied: pydantic<3,>=1 in /usr/local/lib/python3.10/dist-packages (from langchain) (2.7.4)\n",
      "Requirement already satisfied: requests<3,>=2 in /usr/local/lib/python3.10/dist-packages (from langchain) (2.31.0)\n",
      "Requirement already satisfied: tenacity!=8.4.0,<9.0.0,>=8.1.0 in /usr/local/lib/python3.10/dist-packages (from langchain) (8.4.1)\n",
      "Collecting openai<2.0.0,>=1.32.0 (from langchain_openai)\n",
      "  Downloading openai-1.35.7-py3-none-any.whl (327 kB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m327.5/327.5 kB\u001b[0m \u001b[31m23.6 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hCollecting tiktoken<1,>=0.7 (from langchain_openai)\n",
      "  Downloading tiktoken-0.7.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (1.1 MB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m1.1/1.1 MB\u001b[0m \u001b[31m34.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hCollecting langchain-community<0.3.0,>=0.2.6 (from langchain_experimental)\n",
      "  Downloading langchain_community-0.2.6-py3-none-any.whl (2.2 MB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.2/2.2 MB\u001b[0m \u001b[31m58.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hRequirement already satisfied: click>=8.1.7 in /usr/local/lib/python3.10/dist-packages (from duckduckgo-search) (8.1.7)\n",
      "Collecting pyreqwest-impersonate>=0.4.8 (from duckduckgo-search)\n",
      "  Downloading pyreqwest_impersonate-0.4.8-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (2.7 MB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m2.7/2.7 MB\u001b[0m \u001b[31m60.3 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hCollecting orjson>=3.10.5 (from duckduckgo-search)\n",
      "  Downloading orjson-3.10.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl (144 kB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m145.0/145.0 kB\u001b[0m \u001b[31m3.7 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hRequirement already satisfied: packaging<25,>=23.2 in /usr/local/lib/python3.10/dist-packages (from langchainhub) (24.1)\n",
      "Collecting types-requests<3.0.0.0,>=2.31.0.2 (from langchainhub)\n",
      "  Downloading types_requests-2.32.0.20240622-py3-none-any.whl (15 kB)\n",
      "Requirement already satisfied: transformers<5.0.0,>=4.34.0 in /usr/local/lib/python3.10/dist-packages (from sentence-transformers) (4.41.2)\n",
      "Requirement already satisfied: tqdm in /usr/local/lib/python3.10/dist-packages (from sentence-transformers) (4.66.4)\n",
      "Requirement already satisfied: torch>=1.11.0 in /usr/local/lib/python3.10/dist-packages (from sentence-transformers) (2.3.0+cu121)\n",
      "Requirement already satisfied: scikit-learn in /usr/local/lib/python3.10/dist-packages (from sentence-transformers) (1.2.2)\n",
      "Requirement already satisfied: scipy in /usr/local/lib/python3.10/dist-packages (from sentence-transformers) (1.11.4)\n",
      "Requirement already satisfied: huggingface-hub>=0.15.1 in /usr/local/lib/python3.10/dist-packages (from sentence-transformers) (0.23.4)\n",
      "Requirement already satisfied: Pillow in /usr/local/lib/python3.10/dist-packages (from sentence-transformers) (9.4.0)\n",
      "Requirement already satisfied: aiosignal>=1.1.2 in /usr/local/lib/python3.10/dist-packages (from aiohttp<4.0.0,>=3.8.3->langchain) (1.3.1)\n",
      "Requirement already satisfied: attrs>=17.3.0 in /usr/local/lib/python3.10/dist-packages (from aiohttp<4.0.0,>=3.8.3->langchain) (23.2.0)\n",
      "Requirement already satisfied: frozenlist>=1.1.1 in /usr/local/lib/python3.10/dist-packages (from aiohttp<4.0.0,>=3.8.3->langchain) (1.4.1)\n",
      "Requirement already satisfied: multidict<7.0,>=4.5 in /usr/local/lib/python3.10/dist-packages (from aiohttp<4.0.0,>=3.8.3->langchain) (6.0.5)\n",
      "Requirement already satisfied: yarl<2.0,>=1.0 in /usr/local/lib/python3.10/dist-packages (from aiohttp<4.0.0,>=3.8.3->langchain) (1.9.4)\n",
      "Requirement already satisfied: filelock in /usr/local/lib/python3.10/dist-packages (from huggingface-hub>=0.15.1->sentence-transformers) (3.15.3)\n",
      "Requirement already satisfied: fsspec>=2023.5.0 in /usr/local/lib/python3.10/dist-packages (from huggingface-hub>=0.15.1->sentence-transformers) (2023.6.0)\n",
      "Requirement already satisfied: typing-extensions>=3.7.4.3 in /usr/local/lib/python3.10/dist-packages (from huggingface-hub>=0.15.1->sentence-transformers) (4.12.2)\n",
      "Collecting dataclasses-json<0.7,>=0.5.7 (from langchain-community<0.3.0,>=0.2.6->langchain_experimental)\n",
      "  Downloading dataclasses_json-0.6.7-py3-none-any.whl (28 kB)\n",
      "Collecting jsonpatch<2.0,>=1.33 (from langchain-core<0.3.0,>=0.2.10->langchain)\n",
      "  Downloading jsonpatch-1.33-py2.py3-none-any.whl (12 kB)\n",
      "Requirement already satisfied: anyio<5,>=3.5.0 in /usr/local/lib/python3.10/dist-packages (from openai<2.0.0,>=1.32.0->langchain_openai) (3.7.1)\n",
      "Requirement already satisfied: distro<2,>=1.7.0 in /usr/lib/python3/dist-packages (from openai<2.0.0,>=1.32.0->langchain_openai) (1.7.0)\n",
      "Collecting httpx<1,>=0.23.0 (from openai<2.0.0,>=1.32.0->langchain_openai)\n",
      "  Downloading httpx-0.27.0-py3-none-any.whl (75 kB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m75.6/75.6 kB\u001b[0m \u001b[31m7.1 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hRequirement already satisfied: sniffio in /usr/local/lib/python3.10/dist-packages (from openai<2.0.0,>=1.32.0->langchain_openai) (1.3.1)\n",
      "Requirement already satisfied: annotated-types>=0.4.0 in /usr/local/lib/python3.10/dist-packages (from pydantic<3,>=1->langchain) (0.7.0)\n",
      "Requirement already satisfied: pydantic-core==2.18.4 in /usr/local/lib/python3.10/dist-packages (from pydantic<3,>=1->langchain) (2.18.4)\n",
      "Requirement already satisfied: charset-normalizer<4,>=2 in /usr/local/lib/python3.10/dist-packages (from requests<3,>=2->langchain) (3.3.2)\n",
      "Requirement already satisfied: idna<4,>=2.5 in /usr/local/lib/python3.10/dist-packages (from requests<3,>=2->langchain) (3.7)\n",
      "Requirement already satisfied: urllib3<3,>=1.21.1 in /usr/local/lib/python3.10/dist-packages (from requests<3,>=2->langchain) (2.0.7)\n",
      "Requirement already satisfied: certifi>=2017.4.17 in /usr/local/lib/python3.10/dist-packages (from requests<3,>=2->langchain) (2024.6.2)\n",
      "Requirement already satisfied: greenlet!=0.4.17 in /usr/local/lib/python3.10/dist-packages (from SQLAlchemy<3,>=1.4->langchain) (3.0.3)\n",
      "Requirement already satisfied: regex>=2022.1.18 in /usr/local/lib/python3.10/dist-packages (from tiktoken<1,>=0.7->langchain_openai) (2024.5.15)\n",
      "Requirement already satisfied: sympy in /usr/local/lib/python3.10/dist-packages (from torch>=1.11.0->sentence-transformers) (1.12.1)\n",
      "Requirement already satisfied: networkx in /usr/local/lib/python3.10/dist-packages (from torch>=1.11.0->sentence-transformers) (3.3)\n",
      "Requirement already satisfied: jinja2 in /usr/local/lib/python3.10/dist-packages (from torch>=1.11.0->sentence-transformers) (3.1.4)\n",
      "Collecting nvidia-cuda-nvrtc-cu12==12.1.105 (from torch>=1.11.0->sentence-transformers)\n",
      "  Using cached nvidia_cuda_nvrtc_cu12-12.1.105-py3-none-manylinux1_x86_64.whl (23.7 MB)\n",
      "Collecting nvidia-cuda-runtime-cu12==12.1.105 (from torch>=1.11.0->sentence-transformers)\n",
      "  Using cached nvidia_cuda_runtime_cu12-12.1.105-py3-none-manylinux1_x86_64.whl (823 kB)\n",
      "Collecting nvidia-cuda-cupti-cu12==12.1.105 (from torch>=1.11.0->sentence-transformers)\n",
      "  Using cached nvidia_cuda_cupti_cu12-12.1.105-py3-none-manylinux1_x86_64.whl (14.1 MB)\n",
      "Collecting nvidia-cudnn-cu12==8.9.2.26 (from torch>=1.11.0->sentence-transformers)\n",
      "  Using cached nvidia_cudnn_cu12-8.9.2.26-py3-none-manylinux1_x86_64.whl (731.7 MB)\n",
      "Collecting nvidia-cublas-cu12==12.1.3.1 (from torch>=1.11.0->sentence-transformers)\n",
      "  Using cached nvidia_cublas_cu12-12.1.3.1-py3-none-manylinux1_x86_64.whl (410.6 MB)\n",
      "Collecting nvidia-cufft-cu12==11.0.2.54 (from torch>=1.11.0->sentence-transformers)\n",
      "  Using cached nvidia_cufft_cu12-11.0.2.54-py3-none-manylinux1_x86_64.whl (121.6 MB)\n",
      "Collecting nvidia-curand-cu12==10.3.2.106 (from torch>=1.11.0->sentence-transformers)\n",
      "  Using cached nvidia_curand_cu12-10.3.2.106-py3-none-manylinux1_x86_64.whl (56.5 MB)\n",
      "Collecting nvidia-cusolver-cu12==11.4.5.107 (from torch>=1.11.0->sentence-transformers)\n",
      "  Using cached nvidia_cusolver_cu12-11.4.5.107-py3-none-manylinux1_x86_64.whl (124.2 MB)\n",
      "Collecting nvidia-cusparse-cu12==12.1.0.106 (from torch>=1.11.0->sentence-transformers)\n",
      "  Using cached nvidia_cusparse_cu12-12.1.0.106-py3-none-manylinux1_x86_64.whl (196.0 MB)\n",
      "Collecting nvidia-nccl-cu12==2.20.5 (from torch>=1.11.0->sentence-transformers)\n",
      "  Using cached nvidia_nccl_cu12-2.20.5-py3-none-manylinux2014_x86_64.whl (176.2 MB)\n",
      "Collecting nvidia-nvtx-cu12==12.1.105 (from torch>=1.11.0->sentence-transformers)\n",
      "  Using cached nvidia_nvtx_cu12-12.1.105-py3-none-manylinux1_x86_64.whl (99 kB)\n",
      "Requirement already satisfied: triton==2.3.0 in /usr/local/lib/python3.10/dist-packages (from torch>=1.11.0->sentence-transformers) (2.3.0)\n",
      "Collecting nvidia-nvjitlink-cu12 (from nvidia-cusolver-cu12==11.4.5.107->torch>=1.11.0->sentence-transformers)\n",
      "  Downloading nvidia_nvjitlink_cu12-12.5.40-py3-none-manylinux2014_x86_64.whl (21.3 MB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m21.3/21.3 MB\u001b[0m \u001b[31m39.0 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hRequirement already satisfied: tokenizers<0.20,>=0.19 in /usr/local/lib/python3.10/dist-packages (from transformers<5.0.0,>=4.34.0->sentence-transformers) (0.19.1)\n",
      "Requirement already satisfied: safetensors>=0.4.1 in /usr/local/lib/python3.10/dist-packages (from transformers<5.0.0,>=4.34.0->sentence-transformers) (0.4.3)\n",
      "Requirement already satisfied: joblib>=1.1.1 in /usr/local/lib/python3.10/dist-packages (from scikit-learn->sentence-transformers) (1.4.2)\n",
      "Requirement already satisfied: threadpoolctl>=2.0.0 in /usr/local/lib/python3.10/dist-packages (from scikit-learn->sentence-transformers) (3.5.0)\n",
      "Requirement already satisfied: exceptiongroup in /usr/local/lib/python3.10/dist-packages (from anyio<5,>=3.5.0->openai<2.0.0,>=1.32.0->langchain_openai) (1.2.1)\n",
      "Collecting marshmallow<4.0.0,>=3.18.0 (from dataclasses-json<0.7,>=0.5.7->langchain-community<0.3.0,>=0.2.6->langchain_experimental)\n",
      "  Downloading marshmallow-3.21.3-py3-none-any.whl (49 kB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m49.2/49.2 kB\u001b[0m \u001b[31m5.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hCollecting typing-inspect<1,>=0.4.0 (from dataclasses-json<0.7,>=0.5.7->langchain-community<0.3.0,>=0.2.6->langchain_experimental)\n",
      "  Downloading typing_inspect-0.9.0-py3-none-any.whl (8.8 kB)\n",
      "Collecting httpcore==1.* (from httpx<1,>=0.23.0->openai<2.0.0,>=1.32.0->langchain_openai)\n",
      "  Downloading httpcore-1.0.5-py3-none-any.whl (77 kB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m77.9/77.9 kB\u001b[0m \u001b[31m8.2 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hCollecting h11<0.15,>=0.13 (from httpcore==1.*->httpx<1,>=0.23.0->openai<2.0.0,>=1.32.0->langchain_openai)\n",
      "  Downloading h11-0.14.0-py3-none-any.whl (58 kB)\n",
      "\u001b[2K     \u001b[90m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m58.3/58.3 kB\u001b[0m \u001b[31m6.9 MB/s\u001b[0m eta \u001b[36m0:00:00\u001b[0m\n",
      "\u001b[?25hCollecting jsonpointer>=1.9 (from jsonpatch<2.0,>=1.33->langchain-core<0.3.0,>=0.2.10->langchain)\n",
      "  Downloading jsonpointer-3.0.0-py2.py3-none-any.whl (7.6 kB)\n",
      "Requirement already satisfied: MarkupSafe>=2.0 in /usr/local/lib/python3.10/dist-packages (from jinja2->torch>=1.11.0->sentence-transformers) (2.1.5)\n",
      "Requirement already satisfied: mpmath<1.4.0,>=1.1.0 in /usr/local/lib/python3.10/dist-packages (from sympy->torch>=1.11.0->sentence-transformers) (1.3.0)\n",
      "Collecting mypy-extensions>=0.3.0 (from typing-inspect<1,>=0.4.0->dataclasses-json<0.7,>=0.5.7->langchain-community<0.3.0,>=0.2.6->langchain_experimental)\n",
      "  Downloading mypy_extensions-1.0.0-py3-none-any.whl (4.7 kB)\n",
      "Installing collected packages: types-requests, pyreqwest-impersonate, orjson, nvidia-nvtx-cu12, nvidia-nvjitlink-cu12, nvidia-nccl-cu12, nvidia-curand-cu12, nvidia-cufft-cu12, nvidia-cuda-runtime-cu12, nvidia-cuda-nvrtc-cu12, nvidia-cuda-cupti-cu12, nvidia-cublas-cu12, mypy-extensions, marshmallow, jsonpointer, h11, faiss-cpu, typing-inspect, tiktoken, nvidia-cusparse-cu12, nvidia-cudnn-cu12, langchainhub, jsonpatch, httpcore, duckduckgo-search, nvidia-cusolver-cu12, langsmith, httpx, dataclasses-json, openai, langchain-core, sentence-transformers, langchain-text-splitters, langchain_openai, langchain, langchain-community, langchain_experimental\n",
      "Successfully installed dataclasses-json-0.6.7 duckduckgo-search-6.1.7 faiss-cpu-1.8.0.post1 h11-0.14.0 httpcore-1.0.5 httpx-0.27.0 jsonpatch-1.33 jsonpointer-3.0.0 langchain-0.2.6 langchain-community-0.2.6 langchain-core-0.2.10 langchain-text-splitters-0.2.2 langchain_experimental-0.0.62 langchain_openai-0.1.13 langchainhub-0.1.20 langsmith-0.1.82 marshmallow-3.21.3 mypy-extensions-1.0.0 nvidia-cublas-cu12-12.1.3.1 nvidia-cuda-cupti-cu12-12.1.105 nvidia-cuda-nvrtc-cu12-12.1.105 nvidia-cuda-runtime-cu12-12.1.105 nvidia-cudnn-cu12-8.9.2.26 nvidia-cufft-cu12-11.0.2.54 nvidia-curand-cu12-10.3.2.106 nvidia-cusolver-cu12-11.4.5.107 nvidia-cusparse-cu12-12.1.0.106 nvidia-nccl-cu12-2.20.5 nvidia-nvjitlink-cu12-12.5.40 nvidia-nvtx-cu12-12.1.105 openai-1.35.7 orjson-3.10.5 pyreqwest-impersonate-0.4.8 sentence-transformers-3.0.1 tiktoken-0.7.0 types-requests-2.32.0.20240622 typing-inspect-0.9.0\n"
     ]
    }
   ],
   "source": [
    "import os\n",
    "\n",
    "try:\n",
    "    from google.colab import drive, userdata\n",
    "    COLAB = True\n",
    "    print(\"Note: using Google CoLab\")\n",
    "except:\n",
    "    print(\"Note: not using Google CoLab\")\n",
    "    COLAB = False\n",
    "\n",
    "# OpenAI Secrets\n",
    "if COLAB:\n",
    "    os.environ[\"OPENAI_API_KEY\"] = userdata.get('OPENAI_API_KEY')\n",
    "    os.environ[\"TAVILY_API_KEY\"] = userdata.get('TAVILY_API_KEY')\n",
    "\n",
    "# Install needed libraries in CoLab\n",
    "if COLAB:\n",
    "    !pip install langchain langchain_openai langchain_experimental duckduckgo-search langchainhub sentence-transformers faiss-cpu"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "pC9A-LaYhsta"
   },
   "source": [
    "# 7.4: Constructing LangChain Agents\n",
    "\n",
    "\n",
    "In this chapter, we introduce a comprehensive module that showcases the capabilities of a complete LangChain agent equipped with web search, retrieval, and memory functionalities. This agent is designed to answer questions by leveraging the most up-to-date documentation about LangChain through Retrieval-Augmented Generation (RAG), surpassing the limitations of the foundational model's knowledge. By integrating real-time web search and retrieval, the agent can access and incorporate the latest information, ensuring its responses are accurate and current. Additionally, the memory component enables the agent to retain and recall pertinent information, enhancing its ability to provide informed and contextually relevant answers. Through this module, readers will learn how to create an intelligent agent that not only understands and processes queries but also continually updates its knowledge base to stay aligned with the latest advancements in LangChain.\n",
    "\n",
    "We begin by importing the necessary libraries and modules required for our LangChain agent, including those for web search, retrieval, and memory management. Just as we have done in previous chapters, we will create an OpenAI language model (LLM) to serve as the foundation of our agent. This model will be pivotal in interpreting and generating human-like text based on the input it receives. By leveraging the OpenAI LLM, we ensure our agent has a robust and versatile language understanding capability, which will be further enhanced by integrating real-time web search and retrieval functionalities. This setup allows the agent to access and utilize the most recent and relevant information, providing comprehensive and accurate responses to user queries.\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "NuSzXAi7XhmT",
    "outputId": "19eb8ddf-e5d9-4356-aa97-db74365ef918"
   },
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "WARNING:langchain_community.utils.user_agent:USER_AGENT environment variable not set, consider setting it to identify your requests.\n"
     ]
    }
   ],
   "source": [
    "from langchain_community.tools.tavily_search import TavilySearchResults\n",
    "from langchain_openai import ChatOpenAI\n",
    "from langchain import hub\n",
    "from langchain_community.document_loaders import WebBaseLoader\n",
    "from langchain_community.vectorstores import FAISS\n",
    "from langchain_openai import OpenAIEmbeddings\n",
    "from langchain_text_splitters import RecursiveCharacterTextSplitter\n",
    "from langchain.tools.retriever import create_retriever_tool\n",
    "from langchain.agents import create_tool_calling_agent\n",
    "from langchain.agents import AgentExecutor\n",
    "\n",
    "MODEL = 'gpt-4o-mini'\n",
    "\n",
    "llm = ChatOpenAI(\n",
    "        model=MODEL,\n",
    "        temperature=0.2,\n",
    "        n=1\n",
    "    )"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "nrKUtES1xInM"
   },
   "source": [
    "\n",
    "In this section, we use Retrieval-Augmented Generation (RAG) to access the latest version of the LangChain documentation, which is more current than the data the foundational model was initially trained on. We start by creating a WebBaseLoader instance to load content from the URL https://docs.smith.langchain.com/overview, ensuring we are working with the most recent documentation. Once the content is loaded, we use RecursiveCharacterTextSplitter to break the text into smaller, manageable chunks of 1000 characters each, with an overlap of 200 characters to maintain context. These chunks are then converted into embeddings using OpenAIEmbeddings(), and we index these embeddings with FAISS (Facebook AI Similarity Search) for efficient similarity searching. Finally, we create a retriever from the FAISS index, enabling our LangChain agent to query the document embeddings and retrieve the most relevant chunks of documentation in response to user questions. This approach ensures that our agent can leverage the latest information, enhancing its ability to provide accurate and up-to-date answers."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {
    "id": "kPYRfk33su71"
   },
   "outputs": [],
   "source": [
    "loader = WebBaseLoader(\"https://docs.smith.langchain.com/overview\")\n",
    "docs = loader.load()\n",
    "documents = RecursiveCharacterTextSplitter(\n",
    "    chunk_size=1000, chunk_overlap=200\n",
    ").split_documents(docs)\n",
    "vector = FAISS.from_documents(documents, OpenAIEmbeddings())\n",
    "retriever = vector.as_retriever()"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "twXh4cQHxMqb"
   },
   "source": [
    "We now submit a simple query to the retriever to see what data it returns to answer the quest. The returned data is from the website, not yet processed by a LLM."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "Mh9Wn2HAcFz5",
    "outputId": "ea34e71b-36bb-455d-ab7d-8d7af83f4bce"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Document(page_content='description=\"A sample dataset in LangSmith.\")client.create_examples(    inputs=[        {\"postfix\": \"to LangSmith\"},        {\"postfix\": \"to Evaluations in LangSmith\"},    ],    outputs=[        {\"output\": \"Welcome to LangSmith\"},        {\"output\": \"Welcome to Evaluations in LangSmith\"},    ],    dataset_id=dataset.id,)# Define your evaluatordef exact_match(run, example):    return {\"score\": run.outputs[\"output\"] == example.outputs[\"output\"]}experiment_results = evaluate(    lambda input: \"Welcome \" + input[\\'postfix\\'], # Your AI system goes here    data=dataset_name, # The data to predict and grade over    evaluators=[exact_match], # The evaluators to score the results    experiment_prefix=\"sample-experiment\", # The name of the experiment    metadata={      \"version\": \"1.0.0\",      \"revision_id\": \"beta\"    },)import { Client, Run, Example } from \"langsmith\";import { evaluate } from \"langsmith/evaluation\";import { EvaluationResult } from \"langsmith/evaluation\";const client = new', metadata={'source': 'https://docs.smith.langchain.com/overview', 'title': 'Get started with LangSmith | \\uf8ffü¶úÔ∏è\\uf8ffüõ†Ô∏è LangSmith', 'description': 'LangSmith is a platform for building production-grade LLM applications. It allows you to closely monitor and evaluate your application, so you can ship quickly and with confidence. Use of LangChain is not necessary - LangSmith works on its own!', 'language': 'en'})"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "retriever.invoke(\"how to upload a dataset\")[0]"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "IYY0XPDrxhmp"
   },
   "source": [
    "To provide access to the web data we just downloaded, we use an agent retriever tool. This tool is created by wrapping the retriever we previously built with the VectorStoreRetrieverTool class, specifying \"Documentation\" as the name and a brief description to indicate its purpose. By integrating this agent retriever tool, our LangChain agent can effectively utilize the web data for generating responses. The ZeroShotAgent is then configured with this tool, and the agent is initialized with AgentExecutor. This setup empowers our agent to retrieve and process the most relevant information from the latest LangChain documentation, ensuring it can answer queries accurately and comprehensively."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "metadata": {
    "id": "iH68G5AMcOCA"
   },
   "outputs": [],
   "source": [
    "retriever_tool = create_retriever_tool(\n",
    "    retriever,\n",
    "    \"langsmith_search\",\n",
    "    \"Search for information about LangSmith. For any questions about LangSmith, you must use this tool!\",\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "t5_lEQWJxzcj"
   },
   "source": [
    "We also demonstrate a query to the Tavily search, this will allow us to augment the downloaded data with adhoc web searches to augment both the foundation model and RAG data source."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "7tI0U0PtsIKC",
    "outputId": "e1999af9-b7ee-4515-beeb-2a7ba3436b16"
   },
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[{'url': 'https://www.weatherapi.com/',\n",
       "  'content': \"{'location': {'name': 'San Francisco', 'region': 'California', 'country': 'United States of America', 'lat': 37.78, 'lon': -122.42, 'tz_id': 'America/Los_Angeles', 'localtime_epoch': 1719777546, 'localtime': '2024-06-30 12:59'}, 'current': {'last_updated_epoch': 1719776700, 'last_updated': '2024-06-30 12:45', 'temp_c': 22.2, 'temp_f': 72.0, 'is_day': 1, 'condition': {'text': 'Sunny', 'icon': '//cdn.weatherapi.com/weather/64x64/day/113.png', 'code': 1000}, 'wind_mph': 13.6, 'wind_kph': 22.0, 'wind_degree': 270, 'wind_dir': 'W', 'pressure_mb': 1016.0, 'pressure_in': 29.99, 'precip_mm': 0.01, 'precip_in': 0.0, 'humidity': 55, 'cloud': 0, 'feelslike_c': 24.6, 'feelslike_f': 76.4, 'windchill_c': 17.4, 'windchill_f': 63.3, 'heatindex_c': 17.4, 'heatindex_f': 63.3, 'dewpoint_c': 11.9, 'dewpoint_f': 53.3, 'vis_km': 16.0, 'vis_miles': 9.0, 'uv': 4.0, 'gust_mph': 18.1, 'gust_kph': 29.2}}\"},\n",
       " {'url': 'https://www.msn.com/en-us/weather/topstories/san-francisco-bay-area-june-30-2024/vi-BB1p9I3z',\n",
       "  'content': 'Drop A Flavor Bomb On Your Buttered Noodles With One Secret Sauce'},\n",
       " {'url': 'https://world-weather.info/forecast/usa/san_francisco/june-2024/',\n",
       "  'content': 'Extended weather forecast in San Francisco. Hourly Week 10 days 14 days 30 days Year. Detailed ⚡ San Francisco Weather Forecast for June 2024 - day/night 🌡️ temperatures, precipitations - World-Weather.info.'},\n",
       " {'url': 'https://www.accuweather.com/en/us/san-francisco/94103/june-weather/347629',\n",
       "  'content': 'Get the monthly weather forecast for San Francisco, CA, including daily high/low, historical averages, to help you plan ahead.'},\n",
       " {'url': 'https://www.wunderground.com/hourly/us/ca/san-francisco/94145/date/2024-6-30',\n",
       "  'content': 'San Francisco Weather Forecasts. Weather Underground provides local & long-range weather forecasts, weatherreports, maps & tropical weather conditions for the San Francisco area.'}]"
      ]
     },
     "execution_count": 6,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "search = TavilySearchResults()\n",
    "\n",
    "search.invoke(\"what is the weather in SF\")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "eSBVXZ0QyAdQ"
   },
   "source": [
    "Next we set up the LangChain agent by integrating various tools and configuring the agent to use them effectively. We begin by defining a list of tools that includes our web search tool and the previously created retriever tool. Next, we pull a pre-defined prompt from the LangChain hub using hub.pull(\"hwchase17/openai-functions-agent\"), which provides structured messages that guide the agent's interactions. Using this prompt, we create a tool-calling agent with the create_tool_calling_agent function, passing in our language model (LLM), the list of tools, and the prompt. Finally, we initialize the agent executor with AgentExecutor, specifying the agent and tools, and enabling verbose mode for detailed logging. This setup ensures that our LangChain agent is well-equipped to leverage both the web search and retrieval functionalities to provide accurate and up-to-date responses."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {
    "id": "8dQix3CKsN7X"
   },
   "outputs": [],
   "source": [
    "tools = [search, retriever_tool]\n",
    "\n",
    "# Get the prompt to use - you can modify this!\n",
    "prompt = hub.pull(\"hwchase17/openai-functions-agent\")\n",
    "prompt.messages\n",
    "\n",
    "agent = create_tool_calling_agent(llm, tools, prompt)\n",
    "\n",
    "agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "qy7KYYAPynxP"
   },
   "source": [
    "We can see how the agent responds to a simple trivial prompt."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "Mf6hbRpLbdj9",
    "outputId": "6a0c06f1-68b2-4e5f-c5fb-ce5948399699"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mHello! How can I assist you today?\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'input': 'hi!', 'output': 'Hello! How can I assist you today?'}"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "agent_executor.invoke({\"input\": \"hi!\"})\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "4ck1qk-NysM-"
   },
   "source": [
    "Next we present it with a question about langsmith, we can see the agent utilizes several tools."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "lEXPEYqMsQ8p",
    "outputId": "747d2c78-dc00-48dc-d306-a1dfa97902cf"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m\n",
      "Invoking: `langsmith_search` with `{'query': 'how can LangSmith help with testing'}`\n",
      "\n",
      "\n",
      "\u001b[0m\u001b[33;1m\u001b[1;3mGet started with LangSmith | ü¶úÔ∏èüõ†Ô∏è LangSmith\n",
      "\n",
      "Skip to main contentGo to API DocsSearchGo to AppQuick startTutorialsHow-to guidesConceptsReferencePricingSelf-hostingLangGraph CloudQuick startOn this pageGet started with LangSmithLangSmith is a platform for building production-grade LLM applications. It allows you to closely monitor and evaluate your application, so you can ship quickly and with confidence. Use of LangChain is not necessary - LangSmith works on its own!1. Install LangSmith‚ÄãPythonTypeScriptpip install -U langsmithyarn add langchain langsmith2. Create an API key‚ÄãTo create an API key head to the Settings page. Then click Create API Key.3. Set up your environment‚ÄãShellexport LANGCHAIN_TRACING_V2=trueexport LANGCHAIN_API_KEY=<your-api-key># The below examples use the OpenAI API, though it's not necessary in generalexport OPENAI_API_KEY=<your-openai-api-key>4. Log your first trace‚ÄãWe provide multiple ways to log traces to LangSmith. Below, we'll highlight\n",
      "\n",
      "score: run.outputs?.output === example?.outputs?.output,  };};await evaluate(  (input: { postfix: string }) => ({ output: `Welcome ${input.postfix}` }),  {    data: datasetName,    evaluators: [exactMatch],    metadata: {      version: \"1.0.0\",      revision_id: \"beta\",    },  });Learn more about evaluation in the how-to guides.Was this page helpful?You can leave detailed feedback on GitHub.NextTutorials1. Install LangSmith2. Create an API key3. Set up your environment4. Log your first trace5. Run your first evaluationCommunityDiscordTwitterGitHubDocs CodeLangSmith SDKPythonJS/TSMoreHomepageBlogLangChain Python DocsLangChain JS/TS DocsCopyright ¬© 2024 LangChain, Inc.\n",
      "\n",
      "\"revision_id\": \"beta\"    },)import { Client, Run, Example } from \"langsmith\";import { evaluate } from \"langsmith/evaluation\";import { EvaluationResult } from \"langsmith/evaluation\";const client = new Client();// Define dataset: these are your test casesconst datasetName = \"Sample Dataset\";const dataset = await client.createDataset(datasetName, {  description: \"A sample dataset in LangSmith.\",});await client.createExamples({  inputs: [    { postfix: \"to LangSmith\" },    { postfix: \"to Evaluations in LangSmith\" },  ],  outputs: [    { output: \"Welcome to LangSmith\" },    { output: \"Welcome to Evaluations in LangSmith\" },  ],  datasetId: dataset.id,});// Define your evaluatorconst exactMatch = async (  run: Run,  example: Example): Promise<EvaluationResult> => {  return {    key: \"exact_match\",    score: run.outputs?.output === example?.outputs?.output,  };};await evaluate(  (input: { postfix: string }) => ({ output: `Welcome ${input.postfix}` }),  {    data: datasetName,    evaluators:\u001b[0m\u001b[32;1m\u001b[1;3mLangSmith can help with testing by providing a platform for building production-grade LLM (Large Language Model) applications. It allows you to closely monitor and evaluate your application, ensuring that you can ship quickly and with confidence. LangSmith works independently, so the use of LangChain is not necessary. Here are some steps to get started with LangSmith for testing:\n",
      "\n",
      "1. Install LangSmith using Python or TypeScript:\n",
      "   - Python: `pip install -U langsmith`\n",
      "   - TypeScript: `yarn add langchain langsmith`\n",
      "\n",
      "2. Create an API key:\n",
      "   - Head to the Settings page and click on Create API Key.\n",
      "\n",
      "3. Set up your environment:\n",
      "   - Export the necessary environment variables like `LANGCHAIN_TRACING_V2`, `LANGCHAIN_API_KEY`, and optionally `OPENAI_API_KEY`.\n",
      "\n",
      "4. Log your first trace:\n",
      "   - LangSmith provides multiple ways to log traces. You can log your first trace to start testing your application.\n",
      "\n",
      "LangSmith also offers features like creating datasets, examples, and evaluators for testing purposes. It allows you to evaluate your models and test cases efficiently. For more detailed information, you can refer to the LangSmith documentation and tutorials on their website.\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'input': 'how can langsmith help with testing?',\n",
       " 'output': 'LangSmith can help with testing by providing a platform for building production-grade LLM (Large Language Model) applications. It allows you to closely monitor and evaluate your application, ensuring that you can ship quickly and with confidence. LangSmith works independently, so the use of LangChain is not necessary. Here are some steps to get started with LangSmith for testing:\\n\\n1. Install LangSmith using Python or TypeScript:\\n   - Python: `pip install -U langsmith`\\n   - TypeScript: `yarn add langchain langsmith`\\n\\n2. Create an API key:\\n   - Head to the Settings page and click on Create API Key.\\n\\n3. Set up your environment:\\n   - Export the necessary environment variables like `LANGCHAIN_TRACING_V2`, `LANGCHAIN_API_KEY`, and optionally `OPENAI_API_KEY`.\\n\\n4. Log your first trace:\\n   - LangSmith provides multiple ways to log traces. You can log your first trace to start testing your application.\\n\\nLangSmith also offers features like creating datasets, examples, and evaluators for testing purposes. It allows you to evaluate your models and test cases efficiently. For more detailed information, you can refer to the LangSmith documentation and tutorials on their website.'}"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "agent_executor.invoke({\"input\": \"how can langsmith help with testing?\"})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "G8yXee8-y1Cf"
   },
   "source": [
    "We can also ask it a current events question, causing the agent to go to the search tool."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "9CHdOOn2sRlL",
    "outputId": "c91f1743-f95c-45a1-a7c2-ade3c0f8fe84"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m\n",
      "Invoking: `tavily_search_results_json` with `{'query': 'weather in San Francisco'}`\n",
      "\n",
      "\n",
      "\u001b[0m\u001b[36;1m\u001b[1;3m[{'url': 'https://www.cbsnews.com/philadelphia/news/pa-weather-today-june-8-2024-philadelphia-jersey-shore/', 'content': \"Watch CBS News Beautiful, sunny weather around Philadelphia and Jersey Shore Saturday, rain could return Sunday By Tammie Souza June 8, 2024 / 9:43 AM EDT / CBS Philadelphia PHILADELPHIA (CBS) -- High pressure is in control of the weather here in the Philadelphia area, and it will be a sunny, wonderful day with a light breeze and a high of 83 degrees in the city.  We hit 88 degrees by Thursday and could be passing 90 degrees on Friday and the heat dome over the western U.S. slides east toward us at the end of the week.  Friday could be the start of a stretch of 90-degree days in Philadelphia, even though we haven't even reached the start of astronomical summer yet - that's on June 20 at 4:51 p.m.  68 NEXT Weather Radars Hourly Forecast First published on June 8, 2024 / 9:43 AM EDT \"}, {'url': 'https://www.gjsentinel.com/news/western_colorado/north-ave-back-open-after-law-enforcement-incident/article_f4f03298-034c-11ef-882f-3b2bfc4cc368.html', 'content': 'Low near 50F. Winds SE at 10 to 15 mph. Chance of Rain: 22% Sunrise: 06:15:05 AM Sunset: 08:07:39 PM Humidity: 25% Wind: WSW @ 15 mph UV Index: 8 Very High Partly cloudy skies. Chance of Rain: 63% Sunrise: 06:19:59 AM Sunset: 08:03:49 PM Humidity: 74% Wind: N @ 10 mph UV Index: 3 Moderate Showers in the evening, then partly cloudy overnight. Chance of Rain: 3% Sunrise: 06:16:17 AM Sunset: 08:06:42 PM Humidity: 25% Wind: NW @ 14 mph UV Index: 8 Very High Clear to partly cloudy. Chance of Rain: 24% Sunrise: 06:18:44 AM Sunset: 08:04:47 PM Humidity: 53% Wind: N @ 9 mph UV Index: 8 Very High A few clouds. Chance of Rain: 2% Sunrise: 06:17:30 AM Sunset: 08:05:44 PM Humidity: 32% Wind: SSW @ 13 mph UV Index: 8 Very High A few clouds.'}, {'url': 'https://www.elkintribune.com/apg_sister_paper/yadkin/foreign-investors-must-report-u-s-agricultural-land-holdings/article_a45930c4-0505-58b8-b0d7-14837282eddc.html', 'content': 'Featured Local Savings Recommended for you Trending Now Local Events Chance of Rain: 7% Sunrise: 06:31:38 AM Sunset: 08:09:43 PM Humidity: 63% Wind: SSW @ 9 mph UV Index: 0 Chance of Rain: 58% Sunrise: 06:25:13 AM Sunset: 08:14:49 PM Humidity: 76% Wind: SSE @ 6 mph UV Index: 6 High Considerable cloudiness with occasional rain showers. Chance of Rain: 16% Sunrise: 06:27:16 AM Sunset: 08:13:08 PM Humidity: 58% Wind: SE @ 7 mph UV Index: 7 High Considerable cloudiness with occasional rain showers. Chance of Rain: 58% Sunrise: 06:26:14 AM Sunset: 08:13:59 PM Humidity: 79% Wind: SE @ 6 mph UV Index: 4 Moderate Cloudy with occasional rain showers. Chance of Rain: 24% Sunrise: 06:30:31 AM Sunset: 08:10:34 PM Humidity: 66% Wind: SSW @ 10 mph UV Index: 5 Moderate Cloudy skies early, then partly cloudy after midnight.'}, {'url': 'http://www.sfchronicle.com/weather-forecast/article/california-thunderstorm-dry-lightning-19532152.php', 'content': \"Here's a timeline of impacts Your Daily Puzzles Pile-Up Poker Cross|word Flipart SpellTower Top of the News Exclusive: This troubled S.F. neighborhood could get a monthly block party with outdoor drinking San Francisco has seen the most dramatic drop in solar adoption across California Northern California thunderstorm, dry lightning threat peaks today Giants honor Willie Mays in touching tribute at Oracle Park: ‘He was our guy’ Best Italian restaurants in the Bay Area About Contact Services Account The North Bay, East Bay and Sacramento Valley have the highest chances of thunderstorms during the morning and early afternoon, with the threat shifting northeastward to the Sierra Nevada by the evening. He joins the Chronicle from the University of Washington where he was previously the president of the campus weather forecasting team and an editor at the student newspaper, The Daily UW.  He joins the Chronicle from the University of Washington where he was previously the president of the campus weather forecasting team and an editor at the student newspaper, The Daily UW.  Highs will be in the low 60s in Daly City, Pacifica and Half Moon Bay, mid-to upper 60s in South San Francisco and San Bruno and the mid- to upper 70s in San Mateo and Redwood City.\"}, {'url': 'https://www.cbsnews.com/philadelphia/news/sunny-start-philadelphia-wednesday-weather-passing-storms-possible-new-jersey-delaware/', 'content': \"High of 84, low of 58, warm and sunny Monday: High of 79, low of 65, some sun and a shower Tuesday: High of 84, low of 66, chance for a thunderstorm First published on May 29, 2024 / 5:57 AM EDT  Watch CBS News Sunny start in Philadelphia Wednesday, but some passing storms possible this afternoon By Kate Bilo Updated on: May 29, 2024 / 6:00 AM EDT / CBS Philadelphia PHILADELPHIA (CBS) -- Wednesday starts out with lots of sunshine across the Delaware Valley and high temperatures near 78 degrees.  A few shower chances linger overnight and into Thursday morning, and there's a chance for a sprinkle of a few clouds, but generally the rest of the day will be warm and sunny.  High of 75, low of 58, sunny and cooler Friday: High of 78, low of 55, beautiful day!  The city could get a few rumbles of thunder, but Delaware and the Jersey Shore appear to have the greatest chance of seeing more thunder, lightning and heavier downpours by about 7:30-8 p.m. \"}]\u001b[0m\u001b[32;1m\u001b[1;3mThe weather in San Francisco is currently in the low 60s in Daly City, Pacifica, and Half Moon Bay, mid-to upper 60s in South San Francisco and San Bruno, and the mid-to upper 70s in San Mateo and Redwood City. There is a threat of thunderstorms in the North Bay, East Bay, and Sacramento Valley during the morning and early afternoon, with the threat shifting northeastward to the Sierra Nevada by the evening.\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'input': 'whats the weather in sf?',\n",
       " 'output': 'The weather in San Francisco is currently in the low 60s in Daly City, Pacifica, and Half Moon Bay, mid-to upper 60s in South San Francisco and San Bruno, and the mid-to upper 70s in San Mateo and Redwood City. There is a threat of thunderstorms in the North Bay, East Bay, and Sacramento Valley during the morning and early afternoon, with the threat shifting northeastward to the Sierra Nevada by the evening.'}"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "agent_executor.invoke({\"input\": \"whats the weather in sf?\"})"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "FHvwUtjld_r4"
   },
   "source": [
    "## Adding Chat History/Memory\n",
    "\n",
    "To enhance our LangChain agent's capabilities, we are adding chat memory to enable it to remember previous interactions and maintain context across a conversation. This addition allows the agent to provide more coherent and contextually aware responses. We start by importing necessary modules for managing chat message histories. We then create an instance of ChatMessageHistory to store the messages exchanged during the conversation. By wrapping our existing agent executor with RunnableWithMessageHistory, we integrate the chat memory functionality. This setup ensures that each session can maintain a history of messages, facilitating smoother and more natural interactions with the agent. The code snippet below illustrates this implementation:"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "metadata": {
    "id": "9qHqnYNYZTS3"
   },
   "outputs": [],
   "source": [
    "from langchain_community.chat_message_histories import ChatMessageHistory\n",
    "from langchain_core.runnables.history import RunnableWithMessageHistory\n",
    "\n",
    "message_history = ChatMessageHistory()\n",
    "\n",
    "agent_with_chat_history = RunnableWithMessageHistory(\n",
    "    agent_executor,\n",
    "    # This is needed because in most real world scenarios, a session id is needed\n",
    "    # It isn't really used here because we are using a simple in memory ChatMessageHistory\n",
    "    lambda session_id: message_history,\n",
    "    input_messages_key=\"input\",\n",
    "    history_messages_key=\"chat_history\",\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "9pr4wfiPzc33"
   },
   "source": [
    "We will now test the memory, I begin by introducing myself."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 12,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "ebpiuCU_dhsJ",
    "outputId": "a9c1414e-254f-4e81-9b91-0406226af020"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mHello Jeff! How can I assist you today?\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'input': \"hi! I'm Jeff\",\n",
       " 'chat_history': [],\n",
       " 'output': 'Hello Jeff! How can I assist you today?'}"
      ]
     },
     "execution_count": 12,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "agent_with_chat_history.invoke(\n",
    "    {\"input\": \"hi! I'm Jeff\"},\n",
    "    # This is needed because in most real world scenarios, a session id is needed\n",
    "    # It isn't really used here because we are using a simple in memory ChatMessageHistory\n",
    "    config={\"configurable\": {\"session_id\": \"x123\"}},\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "rNNKcKWozhEr"
   },
   "source": [
    "Next I ask it a question, we can see that it recalls who I am."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 13,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "4PeWelJPdmn9",
    "outputId": "8b9b6d5f-0acd-4da0-e700-d0db2287713e"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3m\n",
      "Invoking: `langsmith_search` with `{'query': 'how can LangSmith help with testing'}`\n",
      "\n",
      "\n",
      "\u001b[0m\u001b[33;1m\u001b[1;3mGet started with LangSmith | ü¶úÔ∏èüõ†Ô∏è LangSmith\n",
      "\n",
      "Skip to main contentGo to API DocsSearchGo to AppQuick startTutorialsHow-to guidesConceptsReferencePricingSelf-hostingLangGraph CloudQuick startOn this pageGet started with LangSmithLangSmith is a platform for building production-grade LLM applications. It allows you to closely monitor and evaluate your application, so you can ship quickly and with confidence. Use of LangChain is not necessary - LangSmith works on its own!1. Install LangSmith‚ÄãPythonTypeScriptpip install -U langsmithyarn add langchain langsmith2. Create an API key‚ÄãTo create an API key head to the Settings page. Then click Create API Key.3. Set up your environment‚ÄãShellexport LANGCHAIN_TRACING_V2=trueexport LANGCHAIN_API_KEY=<your-api-key># The below examples use the OpenAI API, though it's not necessary in generalexport OPENAI_API_KEY=<your-openai-api-key>4. Log your first trace‚ÄãWe provide multiple ways to log traces to LangSmith. Below, we'll highlight\n",
      "\n",
      "score: run.outputs?.output === example?.outputs?.output,  };};await evaluate(  (input: { postfix: string }) => ({ output: `Welcome ${input.postfix}` }),  {    data: datasetName,    evaluators: [exactMatch],    metadata: {      version: \"1.0.0\",      revision_id: \"beta\",    },  });Learn more about evaluation in the how-to guides.Was this page helpful?You can leave detailed feedback on GitHub.NextTutorials1. Install LangSmith2. Create an API key3. Set up your environment4. Log your first trace5. Run your first evaluationCommunityDiscordTwitterGitHubDocs CodeLangSmith SDKPythonJS/TSMoreHomepageBlogLangChain Python DocsLangChain JS/TS DocsCopyright ¬© 2024 LangChain, Inc.\n",
      "\n",
      "\"revision_id\": \"beta\"    },)import { Client, Run, Example } from \"langsmith\";import { evaluate } from \"langsmith/evaluation\";import { EvaluationResult } from \"langsmith/evaluation\";const client = new Client();// Define dataset: these are your test casesconst datasetName = \"Sample Dataset\";const dataset = await client.createDataset(datasetName, {  description: \"A sample dataset in LangSmith.\",});await client.createExamples({  inputs: [    { postfix: \"to LangSmith\" },    { postfix: \"to Evaluations in LangSmith\" },  ],  outputs: [    { output: \"Welcome to LangSmith\" },    { output: \"Welcome to Evaluations in LangSmith\" },  ],  datasetId: dataset.id,});// Define your evaluatorconst exactMatch = async (  run: Run,  example: Example): Promise<EvaluationResult> => {  return {    key: \"exact_match\",    score: run.outputs?.output === example?.outputs?.output,  };};await evaluate(  (input: { postfix: string }) => ({ output: `Welcome ${input.postfix}` }),  {    data: datasetName,    evaluators:\u001b[0m\u001b[32;1m\u001b[1;3mLangSmith can help with testing by providing a platform for building production-grade LLM (Large Language Model) applications. It allows you to closely monitor and evaluate your application, enabling you to ship quickly and with confidence. Here are some steps to get started with LangSmith for testing:\n",
      "\n",
      "1. Install LangSmith:\n",
      "   - Python: `pip install -U langsmith`\n",
      "   - TypeScript: `yarn add langchain langsmith`\n",
      "\n",
      "2. Create an API key:\n",
      "   - Head to the Settings page and click on Create API Key.\n",
      "\n",
      "3. Set up your environment:\n",
      "   - Export the necessary environment variables like `LANGCHAIN_TRACING_V2` and `LANGCHAIN_API_KEY`.\n",
      "\n",
      "4. Log your first trace:\n",
      "   - LangSmith provides multiple ways to log traces. You can log your first trace to start testing.\n",
      "\n",
      "By following these steps, you can leverage LangSmith for testing your applications effectively.\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'input': 'how can LangSmith help with testing',\n",
       " 'chat_history': [HumanMessage(content=\"hi! I'm Jeff\"),\n",
       "  AIMessage(content='Hello Jeff! How can I assist you today?')],\n",
       " 'output': 'LangSmith can help with testing by providing a platform for building production-grade LLM (Large Language Model) applications. It allows you to closely monitor and evaluate your application, enabling you to ship quickly and with confidence. Here are some steps to get started with LangSmith for testing:\\n\\n1. Install LangSmith:\\n   - Python: `pip install -U langsmith`\\n   - TypeScript: `yarn add langchain langsmith`\\n\\n2. Create an API key:\\n   - Head to the Settings page and click on Create API Key.\\n\\n3. Set up your environment:\\n   - Export the necessary environment variables like `LANGCHAIN_TRACING_V2` and `LANGCHAIN_API_KEY`.\\n\\n4. Log your first trace:\\n   - LangSmith provides multiple ways to log traces. You can log your first trace to start testing.\\n\\nBy following these steps, you can leverage LangSmith for testing your applications effectively.'}"
      ]
     },
     "execution_count": 13,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "agent_with_chat_history.invoke(\n",
    "    {\"input\": \"how can LangSmith help with testing\"},\n",
    "    # This is needed because in most real world scenarios, a session id is needed\n",
    "    # It isn't really used here because we are using a simple in memory ChatMessageHistory\n",
    "    config={\"configurable\": {\"session_id\": \"x123\"}},\n",
    ")"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {
    "id": "whx-u4lCzm5B"
   },
   "source": [
    "We can further review and test the memory."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "8Wgx_TVhdyX5",
    "outputId": "e6a84bdc-099a-4e13-d851-5c6c7efbefc8"
   },
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "\n",
      "\n",
      "\u001b[1m> Entering new AgentExecutor chain...\u001b[0m\n",
      "\u001b[32;1m\u001b[1;3mYou are Jeff, and you just asked me about how LangSmith can help with testing. If you have any more questions or need further assistance, feel free to let me know!\u001b[0m\n",
      "\n",
      "\u001b[1m> Finished chain.\u001b[0m\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "{'input': 'Who am I? What did I just ask you about?!',\n",
       " 'chat_history': [HumanMessage(content=\"hi! I'm Jeff\"),\n",
       "  AIMessage(content='Hello Jeff! How can I assist you today?'),\n",
       "  HumanMessage(content='how can LangSmith help with testing'),\n",
       "  AIMessage(content='LangSmith can help with testing by providing a platform for building production-grade LLM (Large Language Model) applications. It allows you to closely monitor and evaluate your application, enabling you to ship quickly and with confidence. Here are some steps to get started with LangSmith for testing:\\n\\n1. Install LangSmith:\\n   - Python: `pip install -U langsmith`\\n   - TypeScript: `yarn add langchain langsmith`\\n\\n2. Create an API key:\\n   - Head to the Settings page and click on Create API Key.\\n\\n3. Set up your environment:\\n   - Export the necessary environment variables like `LANGCHAIN_TRACING_V2` and `LANGCHAIN_API_KEY`.\\n\\n4. Log your first trace:\\n   - LangSmith provides multiple ways to log traces. You can log your first trace to start testing.\\n\\nBy following these steps, you can leverage LangSmith for testing your applications effectively.')],\n",
       " 'output': 'You are Jeff, and you just asked me about how LangSmith can help with testing. If you have any more questions or need further assistance, feel free to let me know!'}"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "agent_with_chat_history.invoke(\n",
    "    {\"input\": \"Who am I? What did I just ask you about?!\"},\n",
    "    # This is needed because in most real world scenarios, a session id is needed\n",
    "    # It isn't really used here because we are using a simple in memory ChatMessageHistory\n",
    "    config={\"configurable\": {\"session_id\": \"x123\"}},\n",
    ")"
   ]
  }
 ],
 "metadata": {
  "anaconda-cloud": {},
  "colab": {
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3.11 (genai)",
   "language": "python",
   "name": "genai"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.8"
  },
  "varInspector": {
   "cols": {
    "lenName": 16,
    "lenType": 16,
    "lenVar": 40
   },
   "kernels_config": {
    "python": {
     "delete_cmd_postfix": "",
     "delete_cmd_prefix": "del ",
     "library": "var_list.py",
     "varRefreshCmd": "print(var_dic_list())"
    },
    "r": {
     "delete_cmd_postfix": ") ",
     "delete_cmd_prefix": "rm(",
     "library": "var_list.r",
     "varRefreshCmd": "cat(var_dic_list()) "
    }
   },
   "types_to_exclude": [
    "module",
    "function",
    "builtin_function_or_method",
    "instance",
    "_Feature"
   ],
   "window_display": false
  }
 },
 "nbformat": 4,
 "nbformat_minor": 4
}
